import {
  useState,
  useRef,
  useCallback,
  useMemo,
  useImperativeHandle,
  Ref,
  forwardRef,
  useEffect,
} from 'react';
import { createPortal } from 'react-dom';
import { Button, List } from 'antd-mobile';
import { inbiz } from '@inbiz/core';
import { defaultProps } from '../../designer/web/schema';
import { useEvents, InbizIcon } from '@inbiz/utils';
import { connect } from '@formily/react';
import './index.less';
import { getTabKeyByData, genKey, TabKey } from '@inbiz/basic/MemberSelect';
import MemberSelect from '@inbiz/basic/WapMemberSelect';
import api from './api';
import { findIndex } from 'lodash';
import { MemberTypeKeyMap } from '../web/consts';
import { getMemberInfo } from '../web/service';
import _ from 'lodash';
import { getLowercase } from './util';
import { getMessage } from '@inbiz/react';

interface IMember {
  [x: string]: any;
  key: string;
  Name: string;
}
[];

export type IProps = {
  placeholder?: string;
  value?: IMember[];
  originValue?: string | string[];
  viewMode?: string;
  callBackEvents?: {
    onChange?: (v: any) => void;
    onCustomConfirm?: (data: any[]) => boolean | Promise<boolean> | undefined;
  };
  emit?: {
    (type: 'onLoad', ...args: any): void;
    (type: 'onOpen', ...args: any): void;
    (type: 'onClose', ...args: any): void;
    (type: 'onBeforeClose', ...args: any): void;
    (type: 'onBeforeOpen', ...args: any): void;
    (type: 'onSelect', ...args: any): void;
    (type: 'onBeforeChange', ...args: any): void;
    (type: 'onChange', ...args: any): void;
  };
  inbiz: inbiz;
  onChange: (v) => void;
  tabs: any[];
  pageSize: number;
  multiple: boolean;
  className?: string;
  departments: {
    [x: string]: any;
    IdentityId: number;
  }[];
  disabled?: boolean;
  readOnly?: boolean;
  controlId: string;
  childModelConfig: boolean;
  selectedType: string;
  storageConfig?: {
    business: string;
    tableData: {
      componentAttr: string;
      modelAttr: string;
    }[];
  };
} & typeof defaultProps;

type IRef = Ref<ReturnType<typeof api>>;

const SelectMember: React.ForwardRefExoticComponent<IProps> &
  IDefaultValueFormat<{ defaultValue: any }> = forwardRef((props, ref: IRef) => {
    const { emit, originValue, value, multiple,tabs, viewMode } = props;
    const valideRef: any = useRef();
    const [visible, _visible] = useState(false);
    const [selectedId, _selectedId] = useState<number[]>([]);
    const [selected, _selected] = useState<any[]>([]);
    const [configEvents] = useEvents(props.callBackEvents, emit);

    const _tabs = useMemo(() => {
      if(tabs?.length > 0){
        if(typeof tabs?.[0] == 'string'){
          return tabs;
        } else {
          return tabs?.map((item) => item?.memberKey);
        };
      } else {
        return [];
      };
    }, [tabs]);

    const setSelected = (sels: any) => {
      let ids = sels.map((v: any) => v?.key);
      _selected(sels);
      _selectedId(ids);
    };

    const change = useCallback(
      (rows) => {
        emit && emit('onBeforeChange', rows);
        props.onChange(rows);
        // 自定义 方法属性，onBeforeChange 存在并返回为true时才能更新value
        // const result = configEvents.current.onBeforeChange?.(rows) ?? true;
        // if (result) {
        //   props.onChange(rows);
        // }
      },
      [emit],
    );
    const [text,$text]=useState()
    const setValue = useCallback(
      (value?: any) => {
        props?.onChange?.(value);
      },
      [props?.multiple],
    );

    useImperativeHandle(
      ref,
      () => {
        return {
          ...api(configEvents, props),
          isValid: () => {
            if (!props.readOnly) {
              return valideRef.current.isValid();
            }
          },
        };
      },
      [props, value],
    );

    const onDeleteSelectItem = useCallback(
      (e, item: any, i?: number) => {
        if (props?.multiple) {
          let selIndex = selectedId.indexOf(item?.key);
          let index = findIndex(value || [], { key: item?.key });
          if (selIndex > -1) {
            let newSelected = [...selected];
            newSelected.splice(selIndex, 1);
            setSelected([...newSelected]);
          }
          if (index > -1) {
            let newValue = [...(value || [])];
            newValue.splice(index, 1);
            setValue(newValue);
          }
        } else {
          setValue(null);
        }
      },
      [selectedId, selected, props?.multiple, value],
    );

    const onDeleteAllSelect = useCallback(() => {
      let newValue = [...value];
      if (newValue?.length) {
        for (let i = newValue.length - 1; i >= 0; i--) {
          let item = newValue[i];
          if (selectedId.indexOf(item?.key) > -1) {
            newValue.splice(i, 1);
          }
        }
      }
      setValue(newValue);
      setSelected([]);
    }, [selectedId, value]);

    const onToggleSelectAll = useCallback(() => {
      let newValue = [...value];
      if (selectedId.length == newValue.length) {
        setSelected([]);
      } else {
        setSelected(newValue);
      }
    }, [selectedId, value]);

    const onCheckboxChange = useCallback(
      (checked, row) => {
        if (props?.multiple) {
          if (checked) {
            if (!selectedId.includes(row?.key)) {
              setSelected([...selected, row]);
            }
          } else {
            if (selectedId.includes(row?.key)) {
              setSelected([...selected.filter((v) => v?.key != row?.key)]);
            }
          }
        } else {
          setSelected(checked ? [row] : []);
        }
      },
      [props?.multiple, selectedId, selected],
    );

    const renderRow = useCallback(
      (item: any, i: number) => {
        let active = selectedId.includes(item?.key);
        let _name =
          props.selectedType == 'nameUsername' && item.userloginname
            ? `${item.name}(${item.userloginname})`
            : item.name;
        return (
          <div
            key={item?.key}
            className={`${'memberRow'} ${active ? 'active' : ''}`}
            onClick={(e) => {
              if (!props.readOnly && props?.multiple) {
                let checked = selectedId.includes(item?.key);
                onCheckboxChange(!checked, item);
              }
            }}
          >
            <span className={'memberName'}>{_name}</span>
            {props.readOnly ? null : (
              <i
                className={'deleteIcon'}
                onClick={(e) => {
                  e.stopPropagation();
                  onDeleteSelectItem(e, item, i);
                }}
              ></i>
            )}
          </div>
        );
      },
      [props.readOnly, props?.multiple, selectedId, onDeleteSelectItem, onCheckboxChange],
    );

    const renderSingle = (item: any) => {
      let _name =
        props.selectedType == 'nameUsername' && item.userloginname
          ? `${item.name}(${item.userloginname})`
          : item.name;
      return (
        <div className={'memberRow-single'}>
          <div className={'memberName-single'}>{_name}</div>
          <div className={'memberName-icon-single'}>
            <i
              className={'deleteIcon'}
              onClick={(e) => {
                e.stopPropagation();
                onDeleteSelectItem(e, item);
              }}
            >
            </i>
          </div>
        </div>
      )
    }
    useEffect(()=>{
      $text(ref?.current?.getText())
    },[value])
    useEffect(() => {
      emit && emit('onLoad', originValue || null);
    }, [originValue]);

    useEffect(() => {
      configEvents.current?.onChange?.(value);
    }, [value]);

    return (
      <>
      {viewMode=='look'?<div style={{fontSize:'16px'}}>{text}</div>:
      <>
              <div
          className={`${'memberSelect'} ${props?.className}`}
          onClick={() => {
            if (!props.inbiz.browser.designer && !props.readOnly) {
              emit && emit('onBeforeOpen');
              _visible(true);
              emit && emit('onOpen');
            }
          }}
        >
          {/* <Input type="hidden" /> */}
          <div className={'selectedWrapper'}>
            <div
              className={'noneSelect'}
              style={{
                textAlign: 'left',
              }}
            >
              {selectedId.length ? null : value?.length ? null : (
                <Button fill="none" className={'pureButton'}>
                  {getMessage(props.placeholder)}
                </Button>
              )}
              {value?.length ? multiple ? (
                <List className={'selectedList'}>{value?.map(renderRow)}</List>
              ) : renderSingle(value?.[0]) : null}
            </div>
          </div>
          <div className={'selectButton'}>
            <Button
              fill="none"
              disabled={props.readOnly}
            >
              <InbizIcon
                type="icon-ic-arrow-right-bold"
                style={{
                  fontSize: 16,
                }}
              />
            </Button>
          </div>
        </div>
        {visible
          ? createPortal(
            <div className={'popup'}>
              <MemberSelect
                {...props}
                selected={value}
                emit={emit}
                onOk={async (selected) => {
                  change(selected);
                  emit && emit('onBeforeClose');
                  if (configEvents?.current?.onCustomConfirm) {
                    let result: boolean | undefined | Promise<boolean> = configEvents?.current?.onCustomConfirm(selected);
                    if (result === true) {
                      return;
                    } else {
                      if (typeof result === 'object' && result?.then) {
                        let asyncCustomConfirm = await result?.then();
                        if (asyncCustomConfirm !== true) {
                          _visible(false);
                          emit && emit('onClose');
                        };
                      } else {
                        _visible(false);
                        emit && emit('onClose');
                      };
                    };
                  } else {
                    _visible(false);
                    emit && emit('onClose');
                  };
                }}
                onCancel={() => {
                  emit && emit('onBeforeClose');
                  _visible(false);
                  emit && emit('onClose');
                }}
                tabs={_tabs}
              />
            </div>,
            document.body,
          )
          : null}
      </>}

      </>
    );
  });

SelectMember.defaultProps = {
  // 请选择
  placeholder: getMessage('EformMemberSelect.lang.plzSelect'),
};

SelectMember.defaultValueFormat = (props) => {
  return props.defaultValue;
};

SelectMember.originValueFormat = (originValue, props: any) => {
  // 单个tab originValue: id || [id,id]
  // 多个tab  originValue: type:id || [type:id,type:id]
  if (!props.childModelConfig && !originValue) {
    return [];
  }
  let tabTypeKey: number | undefined;
  let _tabs: any[] = [];
  if(props?.tabs?.length > 0){
    if(typeof props?.tabs?.[0] == 'string'){
      _tabs = props.tabs;
    } else {
      _tabs = props.tabs?.map((item: { memberKey: string; }) => item?.memberKey);
    };
  };
  if (_tabs.length == 1) {
    tabTypeKey = MemberTypeKeyMap[_tabs[0]];
  };
  let typeIds: any[] = [],
    typeObject = {};

  let mapValue: any = originValue;
  if (!Array.isArray(mapValue)) {
    mapValue = (mapValue || '').split(',');
  }

  mapValue.map((item) => {
    let type, id;
    if (tabTypeKey || tabTypeKey == 0) {
      type = `${tabTypeKey}`;
      id = item;
    } else {
      const [type1, id1] = item.split(':');
      type = type1;
      id = id1;
    }
    if (type && id) {
      typeIds.push([type, id]);
    }
  });

  typeIds.map((item) => {
    if (!typeObject[item[0]]) {
      typeObject[item[0]] = [];
    }
    typeObject[item[0]].push(item[1]);
  });

  let data = Object.keys(typeObject).map((item) => {
    return {
      memberType: item,
      memberIds: typeObject[item].join(','),
    };
  });
  return getMemberInfo(data, props).then((res) => {
    const allObject = {},
      result: any[] = [];
    let typeIdsArr: any[] = [];
    if (res?.result == 0) {
      let _data = res?.data;
      if (props.childModelConfig) {
        let _tableData = props?.storageConfig?.tableData || [];
        _data = _.map(_data, (item) => {
          let _item = item;
          for (let k = 0; k < _tableData?.length; k++) {
            _item[_tableData[k]?.['componentAttr']] = _item?.[_tableData[k]?.['modelAttr']];
          }
          if (_item?.memberarea == '0') {
            _item['userid'] = _item?.id;
          } else if (_item?.memberarea == '3') {
            _item['groupid'] = _item?.id;
          } else if (_item?.memberarea == '4') {
            _item['positionid'] = _item?.id;
          } else if (_item?.memberarea == '5') {
            _item['deptid'] = _item?.id;
          }
          return _item;
        });
      }
      const mapData = (data: any) => {
        data?.map((item: any) => {
          let tabKey = getTabKeyByData(item);
          let tabKeyNumber = MemberTypeKeyMap[tabKey];
          if (tabKey != null && tabKeyNumber != null) {
            let valueKey = '';
            if (props.childModelConfig) {
              switch (item?.memberarea) {
                case 0:
                case '0':
                  valueKey = tabKeyNumber + ':' + item?.userid;
                  break;
                case 3:
                case '3':
                  valueKey = tabKeyNumber + ':' + item?.groupid;
                  break;
                case 4:
                case '4':
                  valueKey = tabKeyNumber + ':' + item?.positionid;
                  break;
                case 5:
                case '5':
                  valueKey = tabKeyNumber + ':' + item?.deptid;
                  break;
                default:
                  break;
              }
              typeIdsArr.push(valueKey?.split(':'));
            } else {
              valueKey = tabKeyNumber + ':' + item.id;
            }
            let key = genKey(tabKey, item);
            item.key = key;
            allObject[valueKey] = item;
          }
        });
      };
      if (props.childModelConfig) {
        mapData(_data);
      } else {
        if (!_.isEmpty(_data.DepartmentInfoList)) {
          let _DepartmentInfoList = getLowercase(_data.DepartmentInfoList);
          mapData(_DepartmentInfoList);
        }
        if (!_.isEmpty(_data.GroupInfoList)) {
          let _GroupInfoList = getLowercase(_data.GroupInfoList);
          mapData(_GroupInfoList);
        }
        if (!_.isEmpty(_data.PositionInfoList)) {
          let _PositionInfoList = getLowercase(_data.PositionInfoList);
          mapData(_PositionInfoList);
        }
        if (!_.isEmpty(_data.UserInfoList)) {
          let _UserInfoList = getLowercase(_data.UserInfoList);
          mapData(_UserInfoList);
        }
      }
    }
    if (props.childModelConfig) {
      typeIdsArr.map((item) => {
        let key = item.join(':');
        if (allObject[key]) {
          result.push(allObject[key]);
        }
      });
    } else {
      typeIds.map((item) => {
        let key = item.join(':');
        if (allObject[key]) {
          result.push(allObject[key]);
        }
      });
    }
    return result;
  });
};

SelectMember.displayName = 'SelectMember';

export default connect(SelectMember);

export type { IProps };
